package com.tg.app.view;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.os.Looper;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.appbase.custom.constant.DeviceStateConstants;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.transition.Transition;
import com.tange.base.toolkit.AppUtil;
import com.tange.base.toolkit.DimenUtil;
import com.tange.module.device.feature.DeviceFeature;
import com.tg.app.R;
import com.tg.app.bean.LocalThumbnail;
import com.tg.app.helper.DeviceHelper;
import com.tg.app.helper.ResolutionHelper;
import com.tg.app.listener.OnPlayerForeSightListener;
import com.tg.app.listener.OnZoomViewListener;
import com.tg.app.util.LocalThumbnailUtils;
import com.tg.app.widget.ForeSightView;
import com.tg.app.widget.PtzControlView;
import com.tg.app.widget.ZoomPanTextureView;
import com.tg.appcommon.android.TGLog;
import com.tg.appcommon.transform.GrayscaleTransformation;
import com.tg.data.bean.DeviceItem;
import com.tg.data.http.entity.AVFrames;
import com.tg.data.media.AudioDecoder;
import com.tg.data.media.DefaultVideoDecoder;
import com.tg.data.media.MjpegVideoDecoder;
import com.tg.data.media.OnMediaFormatChangedListener;
import com.tg.data.media.OnMediaPlayListener;
import com.tg.data.media.OnMediaPlayerResetListener;
import com.tg.data.media.OnScreencapListener;
import com.tg.data.media.VideoDecoder;
import com.tg.data.media.VideoDecoderFactory;

public abstract class CameraPlayerView extends FrameLayout {
    private static final String TAG = "CameraPlayerView";
    protected  int mediaType;
    public final static int PLAYER_ID_MAIN = 0;
    public final static int PLAYER_ID_MINI = 1;
    protected  int currentPlayer;
    protected OnZoomViewListener  onZoomViewListener;
    protected PtzControlView.OnPtzControlTouchListener ptzControlTouchListener;
    protected OnMediaPlayListener onMediaPlayListener;
    protected OnScreencapListener onScreencapListener;
    protected ResolutionHelper resolutionHelper;
    protected OnMediaFormatChangedListener formatChangedListener;
    protected Context mContext;
    protected ZoomPanTextureView textureView;
    protected VideoDecoder mediaSync;
    private boolean mediaSyncReDefined = false;
    protected int nCodecId = 0;
    protected View bgView;
    protected AudioDecoder audioDecoder;
    protected RelativeLayout  baseLayout;
    protected DeviceItem mDevice;
    protected DeviceFeature mDeviceFeature;

    protected  CameraPlayerStatusListener cameraPlayerStatusListener;
    protected  boolean isPlayLive ;
    protected  boolean isUpdateViewSizeEnable;
    protected  boolean isRecording;
    protected int surfaceTextureUpdatedCount = 0;
    protected  boolean isSurfaceTextureUpdated;
    protected OnMediaPlayerResetListener resetListener;
    protected boolean isMjpegVideo = false;

    protected  int speed = 1;
    protected ForeSightView foreSightView;
    protected boolean isForeSightEnable;
    protected OnPlayerForeSightListener foreSightListener;


    protected int mWidth = 0;
    protected int mHeight = 0;
    protected int mCurPlayerHeight = 0;

    public void setCurPlayerHeight(int height){
        this.mCurPlayerHeight = height;
    }

    public int getCurPlayerHeight(){
        return mCurPlayerHeight;
    }
    public void setCameraViewSize(int height) {
        mHeight = Math.max(mHeight,height);
        TGLog.d(TAG, "setLivePortraitLayout8 setCameraViewSize width = " + mWidth + ", height = " + mHeight + ", w = " + AppUtil.getScreenWidth(mContext) +  ", h = " + AppUtil.getScreenHeight(mContext));
    }

    protected int  getVideoSizeHeight(int height){
        return (int) getResources().getDimension(R.dimen.player_height);

    }

    public void prinfInfo(){
        int width = mediaSync.getAlignWidth();
        int height = mediaSync.getAlignHight();
        TGLog.d(TAG, "prinfInfo width = " + width + ", height = " + height);
    }

    public int updateCameraViewSize(){
        int width = mediaSync.getAlignWidth();
        int height = mediaSync.getAlignHight();

        if (height > 0 && width > 0){
            resolutionHelper.addAndSwitchResolution(width,height);
            if (isLandscape()){
                return mWidth * width / height;
            }
            int h = mWidth * height / width;
            TGLog.d("CameraPlayerView", "setLivePortraitLayout19 width = " + mWidth + ", height = " + mHeight + ", w = " + width +  ", height = " + height +  ", h = " + h);
            if (h <= mHeight - DimenUtil.dp2px(mContext, 50)){
                return h;
            }
        }
        return 0;

    }

    public void setForeSightListener(OnPlayerForeSightListener foreSightListener) {
        this.foreSightListener = foreSightListener;
    }

    public void setForeSightEnable(boolean foreSight) {
        isForeSightEnable = foreSight;
        updateForeSight();
    }

    protected void updateForeSight(){
        if (isForeSightEnable&&foreSightView!=null){
            foreSightView.setVisibility(VISIBLE);
            textureView.setZoomRange(1,1);
            foreSightView.setListener((x, y) -> {
                if (foreSightListener!=null){
                    foreSightListener.onForeSightChanged(0,x,y);
                }
            });
        }
    }
    public void setResetListener(OnMediaPlayerResetListener resetListener) {
        this.resetListener = resetListener;
        updateListener();
    }
    public void setUpdateViewSizeEnable(boolean updateViewSizeEnable) {
        isUpdateViewSizeEnable = updateViewSizeEnable;
    }

    public void setLiveViewShow(boolean playLive) {
        isPlayLive = playLive;
    }

    public void setDevice(DeviceItem mDevice) {
        this.mDevice = mDevice;
        setBackgroud();
    }

    public void setBackgroud(){
        setBackgroundClick();
        if (getContext() == null) {
            return;
        }

        if (getContext() instanceof Activity) {
            Activity activity = (Activity) getContext();
            if (activity.isFinishing() || activity.isDestroyed()) {
                return;
            }
        }
        if (mDevice!=null){
            boolean isClosed = !DeviceHelper.isOnline(mDevice)|| mDevice.is_open != DeviceStateConstants.DEVICE_OPEN;
            LocalThumbnail thumbnail = LocalThumbnailUtils.getInstance().getLocalThumbnail(mDevice.uuid);
            if (thumbnail != null && thumbnail.updatedAt > mDevice.start_time && thumbnail.bitmap != null && !thumbnail.bitmap.isRecycled()) {
                setBackgroud(thumbnail.bitmap,null, isClosed);
            } else {
                setBackgroud(null,mDevice.image_path,isClosed);
            }

        }
    }

    public void setPipBtnVisibility(int visibility){

    }
    public void setDeviceFeature(DeviceFeature mDeviceFeature) {
        this.mDeviceFeature = mDeviceFeature;
        this.currentPlayer = mDeviceFeature.currentPlayer;
    }

    public void setOnMediaPlayListener(OnMediaPlayListener onMediaPlayListener) {
        this.onMediaPlayListener = onMediaPlayListener;
        updateListener();
    }
    public void setSendPTZCmd(boolean isSend){
        textureView.setSendPTZCmd(isSend);
    }
    protected abstract void updateListener();

    public void setOnScreencapListener(OnScreencapListener onScreencapListener) {
        this.onScreencapListener = onScreencapListener;
        updateListener();
    }

    public void setFormatChangedListener(OnMediaFormatChangedListener formatChangedListener) {
        this.formatChangedListener = formatChangedListener;
        updateListener();
    }


    public void setOnZoomViewListener(OnZoomViewListener onZoomViewListener) {
        this.onZoomViewListener = onZoomViewListener;
        updateListener();
    }

    public void setPtzControlTouchListener(PtzControlView.OnPtzControlTouchListener ptzControlTouchListener) {
        this.ptzControlTouchListener = ptzControlTouchListener;
        updateListener();
    }

    public CameraPlayerView(Context context) {
        super(context);
        init(context);
    }

    /**
     * 根据具体的视频流编码
     *
     * @param nCodecId
     */
    protected void fixMediaSyncOnce(int nCodecId){
        if (!mediaSyncReDefined) {

            synchronized (CameraPlayerView.class) {

                if (!mediaSyncReDefined) {

                    TGLog.i(TAG, "[createMediaSyncOnce] nCodecId = %x", nCodecId);


                    mediaSync = VideoDecoderFactory.create(nCodecId);
                    int w = 0, h = 0;
                    w = mediaSync.getAlignWidth();
                    h = mediaSync.getAlignHight();

                    TGLog.i(TAG, "setLivePortraitLayout11 [createMediaSyncOnce] w = %x， h = %x", w, h);


                    TGLog.i(TAG, "[createMediaSyncOnce] mediaSync = " + mediaSync);

                    updateListener();

                    mediaSync.start();

                    mediaSyncReDefined = true;

                }
            }
        }
    }

    public void initMediaSync(boolean isMjpegVideo){
        if (this.isMjpegVideo||!isMjpegVideo)return;
        this.isMjpegVideo = isMjpegVideo;
        playerHide();
        mediaSync = new MjpegVideoDecoder();
        TGLog.d(TAG, "videoSyncThread mediaSync");
        mediaSync.setSpeed(speed);
        updateListener();
    }

    public void setDispInfo(int width, int height){
        // 注意：MJPEG 需更新生成的每一帧的大小，否则画面会被裁切
        if (mediaSync instanceof MjpegVideoDecoder){
            ((MjpegVideoDecoder)mediaSync).setDispWidth(width);
            ((MjpegVideoDecoder)mediaSync).setDispHeight(height);
        }

    }


    public CameraPlayerView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public CameraPlayerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }
    protected void init(Context context){
        mContext = context;
        mediaSync = new DefaultVideoDecoder();
        audioDecoder = new AudioDecoder();
        mWidth = AppUtil.getScreenWidth(mContext);
    }
    public abstract void receiveVideoData(@NonNull AVFrames avFrame) ;
    public abstract void receiveVideoMiniData(@NonNull AVFrames avFrame);
    public void receiveAudioData(@NonNull AVFrames avFrame){
        audioDecoder.addAudio(avFrame);
    }
    public void setSpeed(int speed){
        this.speed = speed;
        mediaSync.setSpeed(speed);
        audioDecoder.setSpeed(speed);
    }
    protected  View.OnClickListener onClickListener ;

    protected void setBackgroundClick(){
        onClickListener  = v -> {
            if (onZoomViewListener != null) {
                onZoomViewListener.onSingleClick(false);
            }
        };

    }

    @SuppressLint("UseCompatLoadingForDrawables")
    private Drawable getDefaultDrawable(){
        Drawable drawable;
        if (DeviceHelper.isCar(mDevice)){
            drawable = getResources().getDrawable(com.module.appcommon.R.mipmap.drive_map_default);
        }else {
            drawable = getResources().getDrawable(R.drawable.image_default_rounded_bg);
        }
        return drawable;
    }
    @SuppressLint("CheckResult")
    public void setBackgroud(Bitmap bitmap, String url, boolean disable) {

        if (((Activity) mContext).isFinishing() || ((Activity) mContext).isDestroyed()) {
            return;
        }

        DiskCacheStrategy diskCacheStrategy = DiskCacheStrategy.RESOURCE;
        RequestOptions requestOptions = new RequestOptions().diskCacheStrategy(diskCacheStrategy).dontAnimate();
        if (disable) {
            GrayscaleTransformation transformation = new GrayscaleTransformation();
            RequestOptions other = RequestOptions.bitmapTransform(transformation);
            requestOptions.apply(other);
        }

         SimpleTarget<Drawable> simpleTarget = new SimpleTarget<Drawable>() {
            @Override
            public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
                setBackgroundViewDrawable(resource);
            }

             @Override
             public void onLoadFailed(@Nullable Drawable errorDrawable) {
                 super.onLoadFailed(errorDrawable);
                 Drawable drawable = getDefaultDrawable();
                 setBackgroundViewDrawable(drawable);
             }

             @Override
             public void onLoadStarted(@Nullable Drawable placeholder) {
                 super.onLoadStarted(placeholder);
             }
         };
        if (!((Activity) mContext).isFinishing() && !((Activity) mContext).isDestroyed()) {

            if (TextUtils.isEmpty(url) && bitmap != null && !bitmap.isRecycled()) {
                requestOptions.diskCacheStrategy(DiskCacheStrategy.NONE);
                requestOptions.skipMemoryCache(true);
                Glide.with(this).load(bitmap).thumbnail(0.5f).apply(requestOptions).into(simpleTarget);
            } else if (!TextUtils.isEmpty(url) && bitmap == null) {
                Glide.with(this).load(url).thumbnail(0.5f).apply(requestOptions).into(simpleTarget);
            }
        }

    }
    protected abstract void setBackgroundViewDrawable(Drawable resource);
    public VideoDecoder getMediaSync(){return  mediaSync;}
    public Bitmap getTextureViewBmp(){
       return getTextureViewBmp(mediaSync,textureView);
    }
    protected Bitmap getTextureViewBmp(VideoDecoder mediaSync2, TextureView texture){
        Bitmap bitmap = null;
        if (mediaSync2.getAlignHight() > 0 && isSurfaceTextureUpdated) {
            int w = mediaSync2.getAlignWidth();
            int h = mediaSync2.getAlignHight();
            bitmap = texture.getBitmap(w, h);
        }
        return bitmap;
    }
    protected void textureUpdatedReset(){
        surfaceTextureUpdatedCount = 0;
        isSurfaceTextureUpdated  = false;
    }
    protected void textureUpdated(){
        if (surfaceTextureUpdatedCount>1){
            isSurfaceTextureUpdated = true;
        }
        surfaceTextureUpdatedCount ++;
    }
    public abstract void setAnchorView(View view);
    public abstract void setFloatView(View view);
    public abstract void setListener();

    public void mediaSyncStart() {
        mediaSync.start();
    }

    public boolean isVideoPause() {
        return mediaSync.isVideoPause();
    }

    public void mediaSyncClear() {
        mediaSync.clear();
        audioDecoder.clear();
    }

    public void mediaSyncStop() {
        mediaSync.stop();
        audioDecoder.stop();
    }

    public int getVideoBufferSize() {
        return mediaSync.getVideoBufferSize();
    }

    public void playerHide(){
        mediaSyncClear();
        ViewGroup.LayoutParams layoutParams = textureView.getLayoutParams();
        baseLayout.removeView(textureView);
        textureView.setVisibility(GONE);
        baseLayout.addView(textureView, layoutParams);

    }

    public void setMediaType(int mediaType) {
        this.mediaType = mediaType;
        updateMediaType();
    }

    protected  void updateMediaType(){
        if (!isLivePlayType()&&isForeSightEnable){
            foreSightView.setVisibility(GONE);
        }
        if (mediaSync!=null){
            mediaSync.setPlayType(getMediaType());
        }
    }

    protected int getMediaType(){
        return mediaType;
    }
    protected boolean isLivePlayType(){
        return mediaType == DefaultVideoDecoder.MEDIA_PLAY_TYPE_LIVE;
    }
    protected boolean isCloudPlayType(){
        return mediaType == DefaultVideoDecoder.MEDIA_PLAY_TYPE_CLOUD;
    }
    protected boolean isSdcardPlayType(){
        return mediaType == DefaultVideoDecoder.MEDIA_PLAY_TYPE_SDCARD;
    }
    protected boolean isMainPlayer() {
        return currentPlayer == PLAYER_ID_MAIN;
    }

    public int getCurrentPlayer() {
        return currentPlayer;
    }

    protected float getAspectRatio(){
        return  16.0f / 9;
    }
    public void audioSyncClear(){
        audioDecoder.clear();
    }

    public void  recordStart(){
        mediaSync.recordStart();
        isRecording = true;
    }
    public void  recordEnd(){
        mediaSync.recordEnd(mContext);
        isRecording = false;
    }
    public void resetPlayerLocation(){

    }



    protected  void setVideoSize(ZoomPanTextureView textureView,int width, int height){
        TGLog.d(TAG, "setLivePortraitLayout "+ width +" height: "+height + "，orientation = " + getResources().getConfiguration().orientation);
        TGLog.d(TAG, "setVideoSize width = " + mWidth + ", height = " + mHeight + ", videoWidth = " + mediaSync.getAlignWidth() + ", videoHeight = " + mediaSync.getAlignHight());
        TGLog.d(TAG, "setVideoSize getAspectRatio = " + getAspectRatio());
        int mainVideoHeight = height;
        int mainVideoWidth = width;
        if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
            mainVideoHeight = getVideoSizeHeight(height);
        }else {
            int mWidth = (int) (mainVideoHeight * getAspectRatio());

            if (mainVideoWidth < mWidth) {
                mainVideoHeight = (int) (mainVideoWidth * 1.0f/getAspectRatio());
            } else {
                mainVideoWidth = mWidth;
            }
        }
        TGLog.d(TAG, "setLivePortraitLayout2 "+ mainVideoWidth +" mainVideoHeight: "+ mainVideoHeight);
        updatePlayerViewSize(textureView,mainVideoWidth,mainVideoHeight);
    }
    protected boolean isLandscape() {
        return getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
    }
    protected void  loadingHide(){
        if (cameraPlayerStatusListener!=null){
            cameraPlayerStatusListener.uploadLoading(false);
        }
    }

    protected void updatePlayerViewSize(ZoomPanTextureView textureView,int width, int height){
        TGLog.d(TAG,"updatePlayerViewSize ZoomPanTextureView width:"+width +" height:"+height);
        if (width == 0 || height == 0) return;

        try {
            ViewGroup.LayoutParams params = bgView.getLayoutParams();
            params.width = width;
            params.height = height;
            bgView.setLayoutParams(params);
        }catch (Exception e){
            TGLog.d(TAG,"updatePlayerViewSize ZoomPanTextureView getLocalizedMessage:"+e.getLocalizedMessage() +" getMessage:"+e.getMessage());
            TGLog.d(TAG,"updatePlayerViewSize ZoomPanTextureView myLooper:"+Looper.myLooper() +" mainLooper:"+Looper.getMainLooper() + ", isMain = " + (Looper.myLooper() == Looper.getMainLooper()));
        }

    }

    public void setOnAudioAecmListener(AudioDecoder.OnAudioAecmListener listener){
        if (audioDecoder !=null){
            audioDecoder.setOnAudioAecmListener(listener);
        }
    }
    public void addRecord(byte[] data){
        if (audioDecoder !=null){
            audioDecoder.addRecord(data);
        }
    }

    public void setVideoSyncPts(long pts) {
        audioDecoder.setVideoSyncPts(pts);
    }

    public  void playbackResetMin(){

    }

    public void switchPlayerHide() {
    }

    public abstract void updateView();

    public abstract void analogZoom(float scale,boolean animation,int duration, int channel, String from);
    public abstract void analogOverZoom(float startScale,float endScale,int duration, int channel);

    public  void setMuteOn(boolean isMuteOn){
        if (audioDecoder!=null){
            audioDecoder.setMuteOn(isMuteOn);
        }
    }

    public interface CameraPlayerStatusListener {
        void uploadLoading(boolean isload);
    }
    public void anchorViewShow(){

    }
    public void anchorViewHide(){

    }
    public void pause(){
        audioPause();
        if (mediaSync != null) {
            mediaSync.pause();
        }
    }



    public void audioPause(){
        if (audioDecoder != null) {
            audioDecoder.pause();
        }
    }

    public  void resume(){
        audioResume();
        if (mediaSync != null) {
            mediaSync.resume();
        }
    }

    public  void audioResume(){
        if (audioDecoder != null) {
            audioDecoder.resume();
        }
    }

    public void audioReset(){
        if (audioDecoder !=null){
            audioDecoder.initAudioTrack();
        }
    }
}
